<?php

namespace Agi\Config;


/**
 * 配置
 *
 * @package Agi\Config
 * @author  Janpoem created at 2015/3/11 6:34
 */
class Config implements Impl
{

    /** @var array 空实例容器，存储格式 className => StorageImpl */
    private static $emptyInstances = array();

    /** @var string 配置的命名空间，生成唯一id时的前缀 */
    protected static $namespace = 'base';

    /** @var string 当前实例的唯一id */
    protected $id = '';

    /** @var string 当前实例的简易访问名 */
    protected $name = '';

    /** @var array 配置的数据 */
    protected $data = array();

    /**
     * 生成该配置类唯一ID
     *
     * @param string|null $name
     *
     * @return string
     */
    public static function mkId($name = null)
    {
        if (empty($name))
            $name = self::DEFAULT_NAME;
        return static::$namespace . '#' . $name;
    }

    /**
     * 根据访问名，返回Storage实例
     *
     * @param string|null $name
     *
     * @return Config|Mail|Db
     */
    public static function get($name = null)
    {
        $config = Storage::getConfig(static::mkId($name));
        if ($config === false) {
            $class = get_called_class();
            if (!isset(self::$emptyInstances[$class]))
                self::$emptyInstances[$class] = new static();
            return self::$emptyInstances[$class];
        }
        return $config;
    }

    /**
     * 定义一个本类的配置
     *
     * @param string|null $name
     * @param array       $data
     *
     * @return bool
     */
    public static function define($name = null, array $data = array())
    {
        if (is_array($name)) {
            $data = $name;
            $name = null;
        }
        return Storage::addData(get_called_class(), $name, $data);
    }

    /**
     * 批量定义本类的配置
     *
     * @param array $configs 请确保 $name => array 的数据格式
     *
     * @return int
     */
    public static function defineMulti(array $configs)
    {
        $count = 0;
        foreach ($configs as $name => $config)
            if (static::define($name, $config))
                ++$count;
        return $count;
    }

    /**
     * 构造函数
     *
     * @param string|null $name      访问名
     * @param array       $data      配置数据
     */
    public function __construct($name = null, array $data = array())
    {
        if (empty($name))
            $name = self::DEFAULT_NAME;
        $this->id = static::mkId($name);
        $this->name = $name;
        $this->data = $this->filterData($data);
    }

    /**
     * 动态读取类属性
     *
     * 判断是否有某个属性，使用 isset 方法（isset 的效率比 array_key_exists 要高），
     * 所以如果某个字段为 null，isset 也会返回 false
     *
     * @param string $field
     *
     * @return null
     */
    public function __get($field)
    {
        if (isset($this->data[$field]))
            return $this->data[$field];
        return null;
    }

    /**
     * 数据过滤接口
     *
     * @param array $data
     *
     * @return array
     */
    public function filterData(array $data)
    {
        return $data;
    }

    /**
     * 获取实例的唯一id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }
}
